package utn.tsb.tsbxml;

import java.util.ArrayList;
import java.util.Stack;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class XmlParser {

    private Stack<String> stack;
    private Stack<String[]> params;
    private String xml;
    private Pattern PATTERN;

    public XmlParser(String xml){
        this.xml = xml;
        this.stack = new Stack<String>();
        this.params = new Stack<String[]>();
        PATTERN = Pattern.compile("<([A-Za-z0-9.-_= ()/:!#$%&'\"]+?)>");
    }

    public Nodo parseXml() throws ParsingException{
        Nodo root = new Nodo();
        ArrayList<Nodo> nodos = new ArrayList<Nodo>();

        try{
            while (xml.length() > 0) {
                if(!xml.startsWith("<")){
                    int pos = xml.indexOf("<");
                    String val = "";
                    if(pos != -1){
                        val = this.xml.substring(0, pos);
                    }
                    String tag = this.stack.pop();
                    Nodo nodo = new Nodo(tag, val);
                    String[] atts = this.params.pop();
                    if(atts.length > 1){
                        for(int i = 1; i < atts.length; i++){
                            String[] keyVal = atts[i].split("=");
                            if(keyVal.length > 1){
                                nodo.addAttribute(keyVal[0], keyVal[1]);
                            }
                        }
                    }
                    nodos.add(nodo);
                    pos = xml.indexOf(tag);
                    xml = xml.substring(pos + tag.length() + 1);
                    continue;
                }
                Matcher matcher = PATTERN.matcher(xml);
                if(matcher.find()){
                    String nodo = matcher.group(1).trim();
                    int pos = xml.indexOf(nodo);
                    xml = xml.substring(pos + nodo.length() + 1);
                    if(nodo.endsWith("/")){
                        Nodo nodoTree = new Nodo(nodo, "");
                        nodos.add(nodoTree);
                    }else if(nodo.startsWith("/")){
                        if(this.stack.size() > 0 &&
                        nodo.substring(1, nodo.length()).equalsIgnoreCase(this.stack.lastElement())){
                            String name = this.stack.pop();
                            root.setName(name);
                            break;
                        }
                    }else if(xml.startsWith("<")){
                        String info[] = nodo.split(" ");
                        nodo = info[0].trim();
                        if(info.length > 1){
                            this.params.push(info);
                        }else{
                            this.params.push(new String[]{});
                        }
                        this.stack.add(nodo);
                        nodos.add(this.parseXml());
                    }else{
                        String info[] = nodo.split(" ");
                        nodo = info[0].trim();
                        if(info.length > 1){
                            this.params.push(info);
                        }else{
                            this.params.push(new String[]{});
                        }
                        this.stack.add(nodo);
                    }
                }
            }
        }catch(Exception e){
            throw new ParsingException("El archivo no se pudo parsear.");
        }

        root.setNodos(nodos);
        return root;
    }

}
